/**
 *                            License
 * THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS  
 * CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). 
 * THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW.  
 * ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR  
 * COPYRIGHT LAW IS PROHIBITED.
 * 
 * BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND  
 * AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE  
 * MAY BE CONSIDERED TO BE A CONTRACT,
 * THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED 
 * HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS.
 * 
 */
package lineage.model.gametime;

import java.util.Calendar;
import java.util.List;

import lineage.core.thread.pool.L1ThreadPool;
import lineage.util.PerformanceTimer;
import lineage.util.Util;
import lineage.util.collections.Lists;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 游戏时钟.
 * 
 * @version 2014年3月16日下午2:37:17
 * @author jrwz
 */
public final class L1GameTimeClock {
    private static final Logger LOG = LoggerFactory.getLogger(L1GameTimeClock.class);
    /** 当前时间. */
    private volatile L1GameTime currentTime = L1GameTime.getSystemCurrentTime();
    /** 过去(以前)的时间. */
    private L1GameTime previousTime = null;
    /** 监听器. */
    private final List<L1GameTimeListener> listeners = Lists.newCopyOnWriteArrayList();

    /**
     * 静态初始化器，由JVM来保证线程安全.
     */
    private static class Holder {
        static L1GameTimeClock instance = new L1GameTimeClock();
    }

    /**
     * 取得该类的实例.
     * 
     * @return 类的实例
     */
    public static L1GameTimeClock getInstance() {
        return Holder.instance;
    }

    private L1GameTimeClock() {
        final PerformanceTimer timer = new PerformanceTimer();
        StringBuilder sb = new StringBuilder();
        sb.append("\r\n--------------------------------------------\r\n");
        sb.append("开启线程：游戏时间");

        L1ThreadPool.getInstance().execute(new TimeUpdater());

        sb.append("(L1GameTimeClock.class)\t耗时 ");
        sb.append(timer.elapsedTimeMillis());
        sb.append(" 毫秒");
        sb.append("\r\n--------------------------------------------\r\n");
        Util.message(Util.SYSTEM_MESSAGE, sb.toString());
    }

    /**
     * 更新时间线程.
     */
    private class TimeUpdater implements Runnable {
        @Override
        public void run() {
            try {
                while (true) {
                    previousTime = currentTime;
                    currentTime = L1GameTime.getSystemCurrentTime();
                    notifyChanged();
                    Thread.sleep(500);
                }
            } catch (InterruptedException e) {
                LOG.error(e.getLocalizedMessage(), e);
            } catch (final Exception e) {
                LOG.error(e.getLocalizedMessage(), e);
            }
        }
    }

    /**
     * 是否变化.
     * 
     * @return 如果改变则返回true
     */
    private boolean isFieldChanged(final int field) {
        return previousTime.get(field) != currentTime.get(field);
    }

    /**
     * 变化通知.
     */
    private void notifyChanged() {
        if (isFieldChanged(Calendar.MONTH)) {
            for (final L1GameTimeListener listener : listeners) {
                listener.onMonthChanged(currentTime);
            }
        }
        if (isFieldChanged(Calendar.DAY_OF_MONTH)) {
            for (final L1GameTimeListener listener : listeners) {
                listener.onDayChanged(currentTime);
            }
        }
        if (isFieldChanged(Calendar.HOUR_OF_DAY)) {
            for (final L1GameTimeListener listener : listeners) {
                listener.onHourChanged(this.currentTime);
            }
        }
        if (isFieldChanged(Calendar.MINUTE)) {
            for (final L1GameTimeListener listener : listeners) {
                listener.onMinuteChanged(currentTime);
            }
        }
    }

    /**
     * 取得当前时间.
     * 
     * @return 当前时间
     */
    public L1GameTime currentTime() {
        return currentTime;
    }

    /**
     * 增加监听器.
     * 
     * @param listener
     *            - 监听器对象
     */
    public void addListener(final L1GameTimeListener listener) {
        listeners.add(listener);
    }

    /**
     * 删除监听器.
     * 
     * @param listener
     *            - 监听器对象
     */
    public void removeListener(final L1GameTimeListener listener) {
        listeners.remove(listener);
    }
}
